#ifndef _XTHREAD_SPIN_LOCK_H
#define _XTHREAD_SPIN_LOCK_H

#if defined(__GNUC__)
#if __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<1)
#error GCC version must be greater or equal than 4.1.2
#endif
#include <sched.h>
#else
#error Currently only linux os are supported
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
 volatile long  flag_;
 volatile long* spin_;
}xthread_spin_lock_t;

static inline void xthread_spin_init(xthread_spin_lock_t* lock)
{
#if defined(__GNUC__)
    __sync_and_and_fetch((long*)&lock->flag_,0);
    __sync_lock_test_and_set((long*)&lock->spin_,(long)&lock->flag_);
#endif
}

static inline void xthread_spin_lock(xthread_spin_lock_t* lock)
{
#if defined(__GNUC__)
    for (;0!=__sync_fetch_and_or(lock->spin_,1);)
    {
        sched_yield();
    }
#endif
}

static inline int xthread_spin_trylock(xthread_spin_lock_t* lock)
{
#if defined(__GNUC__)
    return !__sync_fetch_and_or(lock->spin_,1);
#endif
}

static inline void xthread_spin_unlock(xthread_spin_lock_t* lock)
{
#if defined(__GNUC__)
    __sync_and_and_fetch(lock->spin_,0);
#endif
}

static inline int xthread_spin_is_locked(xthread_spin_lock_t* lock)
{
#if defined(__GNUC__)
    return __sync_add_and_fetch(lock->spin_,0);
#endif
}

#ifdef __cplusplus
}
#endif

#endif /* _XTHREAD_SPIN_LOCK_H */